/**
 * FH Technikum-Wien,
 * BICSS - Sommersemester 2011
 *
 * Softwarearchitekturen und Middlewaretechnologien
 * Alcatraz - Remote - Projekt
 * Gruppe B2
 *
 *
 * @author Christian Fossati
 * @author Stefan Schramek
 * @author Michael Strobl
 * @author Sebastian Vogel
 * @author Juergen Zornig
 *
 *
 * @date 2011/03/10
 *
 **/

/*
 * GameGUI.java
 *
 * Created on 27.04.2011, 17:40:10
 */
package at.technikum.sam.remote.alcatraz.client;

import at.falb.games.alcatraz.api.Alcatraz;
import at.falb.games.alcatraz.api.Player;
import at.technikum.sam.remote.alcatraz.commons.Constants;
import at.technikum.sam.remote.alcatraz.commons.GameRegistryException;
import at.technikum.sam.remote.alcatraz.commons.GameStartException;
import at.technikum.sam.remote.alcatraz.commons.IClient;
import at.technikum.sam.remote.alcatraz.commons.NameAlreadyInUseException;
import at.technikum.sam.remote.alcatraz.commons.NotMasterException;
import at.technikum.sam.remote.alcatraz.commons.PlayerAdapter;
import java.rmi.RemoteException;
import java.rmi.server.UnicastRemoteObject;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.swing.JOptionPane;

/**
 * GameGUI.jave
 * 
 * contains all the elements of the user interface which is used on the client
 * side to the register and unregister with the server and to force start a game
 * 
 */
public class GameGUI extends javax.swing.JFrame implements Constants, ClientListener {

    private static ClientImplementation myClient = null;
    private static PlayerAdapter myPlayer = null;
    private static Alcatraz theGame = null;

    /** Creates new form GameGUI */
    public GameGUI() {
        initComponents();
        tfServerHostName.setText(CONF_REGISTRYSERVERHOSTNAME);
        tfServerPort.setText(CONF_REGISTRYSERVERPORT);
        pnRegistered.setVisible(false);
        this.setSize(pnRegisterForm.getSize());

    }

    /** This method is called from within the constructor to
     * initialize the form.
     * WARNING: Do NOT modify this code. The content of this method is
     * always regenerated by the Form Editor.
     */
    @SuppressWarnings("unchecked")
    // <editor-fold defaultstate="collapsed" desc="Generated Code">//GEN-BEGIN:initComponents
    private void initComponents() {

        pnRegisterForm = new javax.swing.JPanel();
        lbPlayerName = new javax.swing.JLabel();
        tfPlayerName = new javax.swing.JTextField();
        lbServerAddress = new javax.swing.JLabel();
        tfServerHostName = new javax.swing.JTextField();
        lbServerPort = new javax.swing.JLabel();
        tfServerPort = new javax.swing.JTextField();
        lbRegisterFormError = new javax.swing.JLabel();
        btRegister = new javax.swing.JButton();
        pnRegistered = new javax.swing.JPanel();
        lbRegisterInfo = new javax.swing.JLabel();
        btForceStart = new javax.swing.JButton();
        btUnregister = new javax.swing.JButton();
        lbRegisteredError = new javax.swing.JLabel();

        setDefaultCloseOperation(javax.swing.WindowConstants.EXIT_ON_CLOSE);
        setTitle("Alcatraz Registration");

        pnRegisterForm.setPreferredSize(new java.awt.Dimension(400, 200));

        lbPlayerName.setText("Player Name");

        lbServerAddress.setText("Server Host Name");

        lbServerPort.setText("Server Port");

        lbRegisterFormError.setFont(new java.awt.Font("Tahoma", 1, 14));
        lbRegisterFormError.setForeground(new java.awt.Color(255, 0, 0));

        btRegister.setText("Register");
        btRegister.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                btRegisterActionPerformed(evt);
            }
        });

        javax.swing.GroupLayout pnRegisterFormLayout = new javax.swing.GroupLayout(pnRegisterForm);
        pnRegisterForm.setLayout(pnRegisterFormLayout);
        pnRegisterFormLayout.setHorizontalGroup(
            pnRegisterFormLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(pnRegisterFormLayout.createSequentialGroup()
                .addContainerGap()
                .addGroup(pnRegisterFormLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
                    .addComponent(lbPlayerName, javax.swing.GroupLayout.PREFERRED_SIZE, 100, javax.swing.GroupLayout.PREFERRED_SIZE)
                    .addGroup(pnRegisterFormLayout.createSequentialGroup()
                        .addGroup(pnRegisterFormLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING, false)
                            .addComponent(lbServerPort, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
                            .addComponent(lbServerAddress, javax.swing.GroupLayout.PREFERRED_SIZE, 117, javax.swing.GroupLayout.PREFERRED_SIZE))
                        .addGroup(pnRegisterFormLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
                            .addComponent(tfPlayerName, javax.swing.GroupLayout.PREFERRED_SIZE, 199, javax.swing.GroupLayout.PREFERRED_SIZE)
                            .addComponent(tfServerHostName, javax.swing.GroupLayout.PREFERRED_SIZE, 199, javax.swing.GroupLayout.PREFERRED_SIZE)
                            .addComponent(tfServerPort, javax.swing.GroupLayout.PREFERRED_SIZE, 199, javax.swing.GroupLayout.PREFERRED_SIZE)
                            .addComponent(btRegister, javax.swing.GroupLayout.PREFERRED_SIZE, 106, javax.swing.GroupLayout.PREFERRED_SIZE)))
                    .addComponent(lbRegisterFormError, javax.swing.GroupLayout.Alignment.TRAILING, javax.swing.GroupLayout.DEFAULT_SIZE, 380, Short.MAX_VALUE))
                .addContainerGap())
        );
        pnRegisterFormLayout.setVerticalGroup(
            pnRegisterFormLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(pnRegisterFormLayout.createSequentialGroup()
                .addContainerGap()
                .addGroup(pnRegisterFormLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
                    .addGroup(pnRegisterFormLayout.createSequentialGroup()
                        .addComponent(lbPlayerName, javax.swing.GroupLayout.PREFERRED_SIZE, 23, javax.swing.GroupLayout.PREFERRED_SIZE)
                        .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                        .addComponent(lbServerAddress, javax.swing.GroupLayout.PREFERRED_SIZE, 23, javax.swing.GroupLayout.PREFERRED_SIZE))
                    .addGroup(pnRegisterFormLayout.createSequentialGroup()
                        .addComponent(tfPlayerName, javax.swing.GroupLayout.PREFERRED_SIZE, 23, javax.swing.GroupLayout.PREFERRED_SIZE)
                        .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                        .addComponent(tfServerHostName, javax.swing.GroupLayout.PREFERRED_SIZE, 23, javax.swing.GroupLayout.PREFERRED_SIZE)
                        .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                        .addGroup(pnRegisterFormLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
                            .addComponent(tfServerPort, javax.swing.GroupLayout.PREFERRED_SIZE, 23, javax.swing.GroupLayout.PREFERRED_SIZE)
                            .addComponent(lbServerPort, javax.swing.GroupLayout.PREFERRED_SIZE, 23, javax.swing.GroupLayout.PREFERRED_SIZE))))
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                .addComponent(btRegister)
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                .addComponent(lbRegisterFormError, javax.swing.GroupLayout.PREFERRED_SIZE, 19, javax.swing.GroupLayout.PREFERRED_SIZE)
                .addContainerGap(54, Short.MAX_VALUE))
        );

        getContentPane().add(pnRegisterForm, java.awt.BorderLayout.NORTH);

        pnRegistered.setPreferredSize(new java.awt.Dimension(400, 200));

        lbRegisterInfo.setFont(new java.awt.Font("Tahoma", 1, 14));

        btForceStart.setText("Force Start");
        btForceStart.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                btForceStartActionPerformed(evt);
            }
        });

        btUnregister.setText("Unregister");
        btUnregister.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                btUnregisterActionPerformed(evt);
            }
        });

        lbRegisteredError.setFont(new java.awt.Font("Tahoma", 1, 14));
        lbRegisteredError.setForeground(new java.awt.Color(255, 0, 0));

        javax.swing.GroupLayout pnRegisteredLayout = new javax.swing.GroupLayout(pnRegistered);
        pnRegistered.setLayout(pnRegisteredLayout);
        pnRegisteredLayout.setHorizontalGroup(
            pnRegisteredLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(pnRegisteredLayout.createSequentialGroup()
                .addContainerGap()
                .addGroup(pnRegisteredLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
                    .addComponent(lbRegisterInfo, javax.swing.GroupLayout.PREFERRED_SIZE, 369, javax.swing.GroupLayout.PREFERRED_SIZE)
                    .addGroup(pnRegisteredLayout.createSequentialGroup()
                        .addGap(69, 69, 69)
                        .addComponent(btForceStart)
                        .addGap(73, 73, 73)
                        .addComponent(btUnregister))
                    .addComponent(lbRegisteredError, javax.swing.GroupLayout.DEFAULT_SIZE, 380, Short.MAX_VALUE))
                .addContainerGap())
        );
        pnRegisteredLayout.setVerticalGroup(
            pnRegisteredLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(pnRegisteredLayout.createSequentialGroup()
                .addContainerGap()
                .addComponent(lbRegisterInfo, javax.swing.GroupLayout.PREFERRED_SIZE, 26, javax.swing.GroupLayout.PREFERRED_SIZE)
                .addGap(18, 18, 18)
                .addGroup(pnRegisteredLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
                    .addComponent(btForceStart)
                    .addComponent(btUnregister))
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                .addComponent(lbRegisteredError, javax.swing.GroupLayout.PREFERRED_SIZE, 28, javax.swing.GroupLayout.PREFERRED_SIZE)
                .addContainerGap(88, Short.MAX_VALUE))
        );

        getContentPane().add(pnRegistered, java.awt.BorderLayout.CENTER);

        pack();
    }// </editor-fold>//GEN-END:initComponents

    private void btRegisterActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_btRegisterActionPerformed

        IClient clientStub = null;

        String playerName = tfPlayerName.getText();
        String serverHostName = tfServerHostName.getText();
        String serverPort = tfServerPort.getText();

        if (playerName.isEmpty() | serverHostName.isEmpty() | serverPort.isEmpty()) {
            lbRegisterFormError.setText(ERR_TEXTFIELDEMPTY);
            return;
        }

        myClient = new ClientImplementation();
        
        // when the call to this method fails something is very wrong
        try {
            clientStub = (IClient) UnicastRemoteObject.exportObject(myClient, 0);
        } catch (RemoteException ex) {
            Logger.getLogger(GameGUI.class.getName()).log(Level.SEVERE, null, ex);
            System.exit(-1);
        } catch (Exception ex) {
            Logger.getLogger(GameGUI.class.getName()).log(Level.SEVERE, null, ex);
            System.exit(-1);
        }
        
        // makes no sense to go on without a client stub
        if (clientStub == null) {
            Logger.getLogger(GameGUI.class.getName()).
                    log(Level.SEVERE, "ClientStub is null");
            System.exit(-1);
        }


        myPlayer = new PlayerAdapter(playerName, myClient);

        try {
            myClient.init(serverHostName, Integer.parseInt(serverPort), myPlayer);
            myClient.installListener(this);

        } catch (Exception ex) {
            Logger.getLogger(GameGUI.class.getName()).log(Level.SEVERE, null, ex);
        }
        
        try {
            registerPlayer();
        } catch (NameAlreadyInUseException ex) {
            Logger.getLogger(GameGUI.class.getName()).log(Level.FINE, null, ex);
            lbRegisterFormError.setText(ERR_NAMEINUSE);
            return;
        } catch (RemoteException ex) {
            Logger.getLogger(GameGUI.class.getName()).log(Level.INFO, null, ex);
            lbRegisterFormError.setText(ERR_SERVERNOTREACHED);
            return;
        } catch (Exception ex) {
           Logger.getLogger(GameGUI.class.getName()).log(Level.WARNING, null, ex);
           lbRegisterFormError.setText(ERR_ERROR);
            return; 
        }
        
        lbRegisterFormError.setText("");
        lbRegisterInfo.setText(
                "Player ".concat(playerName).concat(" is registered with Server"));
        pnRegisterForm.setVisible(false);
        pnRegistered.setVisible(true);
        this.setSize(pnRegistered.getSize());
    }//GEN-LAST:event_btRegisterActionPerformed

    private void btUnregisterActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_btUnregisterActionPerformed

        try {
            myClient.getMasterServer().unregister(myPlayer);
        } catch (GameRegistryException ex) {
            lbRegisteredError.setText(ERR_ERROR);
            return;
        } catch (RemoteException ex) {
            lbRegisteredError.setText(ERR_SERVERNOTREACHED);
            return;
        }
        lbRegisteredError.setText("");
        pnRegisterForm.setVisible(true);
        pnRegistered.setVisible(false);
        this.setSize(pnRegisterForm.getSize());
    }//GEN-LAST:event_btUnregisterActionPerformed

    private void btForceStartActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_btForceStartActionPerformed

        try {
            myClient.getMasterServer().forceStart(myPlayer);
        } catch (GameStartException ex) {
            lbRegisteredError.setText(ERR_NOTENOUGHPLAYER);
            return;
        } catch (RemoteException ex) {
            lbRegisteredError.setText(ERR_SERVERNOTREACHED);
            return;
        }
        lbRegisteredError.setText("");
    }//GEN-LAST:event_btForceStartActionPerformed

    /**
     * the main starting point for the client
     * 
     * @param args the command line arguments
     */
    public static void main(String args[]) {
        java.awt.EventQueue.invokeLater(new Runnable() {

            public void run() {
                new GameGUI().setVisible(true);
            }
        });
    }
    // Variables declaration - do not modify//GEN-BEGIN:variables
    private javax.swing.JButton btForceStart;
    private javax.swing.JButton btRegister;
    private javax.swing.JButton btUnregister;
    private javax.swing.JLabel lbPlayerName;
    private javax.swing.JLabel lbRegisterFormError;
    private javax.swing.JLabel lbRegisterInfo;
    private javax.swing.JLabel lbRegisteredError;
    private javax.swing.JLabel lbServerAddress;
    private javax.swing.JLabel lbServerPort;
    private javax.swing.JPanel pnRegisterForm;
    private javax.swing.JPanel pnRegistered;
    private javax.swing.JTextField tfPlayerName;
    private javax.swing.JTextField tfServerHostName;
    private javax.swing.JTextField tfServerPort;
    // End of variables declaration//GEN-END:variables

    /**
     * Implementation of the ClientListener gameStarted() method
     * 
     * @param game 
     */
    public void gameStarted(Alcatraz game) {
        theGame = game;
        this.setVisible(false);
        theGame.showWindow();

    }
    
    /**
     * Implementation of the ClientListener gameWon() method
     * 
     * @param player 
     */
    public void gameWon(Player player) {
        int option = JOptionPane.showConfirmDialog(
                theGame.getWindow(),
                "Player ".concat(player.getName()).concat(" wins! Do you want to start a new game?"),
                "New Game?",
                JOptionPane.YES_NO_OPTION);

        if (option == JOptionPane.NO_OPTION) {
            System.exit(0);
        } else {

            pnRegisterForm.setVisible(true);
            pnRegistered.setVisible(false);
            this.setSize(pnRegisterForm.getSize());
            theGame.disposeWindow();
            this.setVisible(true);

        }
    }
    
    /**
     * Implementation of the ClientListener playerAbsent() method
     * 
     * @param name 
     */
    public void playerAbsent(String name) {

        JOptionPane.showMessageDialog(
                theGame.getGameBoard(),
                "Player ".concat(name).
                concat(" is absent!"),
                "Player absent",
                JOptionPane.WARNING_MESSAGE);
        Logger.getLogger(GameGUI.class.getName()).
                log(Level.INFO,  "Player ".concat(name).concat(" is absent!"));

    }

    private void registerPlayer() throws Exception {
        try {
            myClient.getMasterServer().register(myPlayer);
        } catch (NotMasterException ex) {
            Logger.getLogger(ClientImplementation.class.getName()).log(Level.FINE, null, ex);
            try {
                myClient.reportNewMaster(ex.getHost(), ex.getPort());
            } catch (RemoteException ex1) {
                throw ex1;
            }
            try { 
                registerPlayer();
            } catch (Exception ex2) {
                throw ex2;
            }
        } catch (Exception ex) {
            throw ex;
        }

    }
}
